﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using BTM_Client_Application.SupportClasses;
using Client_Server_Interface;

namespace BTM_Client_Application.RealTimeFilter
{
    /// <summary>
    /// Логика взаимодействия для StringFilterElementControl.xaml
    /// </summary>
    public partial class StringFilterElementControl : UserControl, FilterElementControl.IFilterElementControl
    {
        private readonly ObservableCollection<FilterListItem> _filterItems;
        private readonly List<object> _availableItems;
        private List<string> _containBoxStrings;
        //private bool _showList;
        private FilterElementType _showType;

        private bool _listEnabled = false;
        private bool _containsEnabled = false;

        private delegate void OnCheckBoxClickDelegate(bool newState, string item);

        public enum FilterInputType
        {
            List,
            WordPartsContains,
            ListAndContains
        }

        private StringFilterElementControl()
        {
            InitializeComponent();

            ListLabel.Content = Res.Rm.GetString("List");
            ContainsLabel.Content = Res.Rm.GetString("Contains");

            Style = FindResource("MyPopup") as Style;
            _availableItems = new List<object>();
            _filterItems = new ObservableCollection<FilterListItem>();
            _containBoxStrings = new List<string>();
            FilterItemsList.IsEnabled = false;
            FilterContainsBox.IsEnabled = false;
            
        }

        public string FilterTitle
        {
            get { return Title.Content.ToString(); }

            set { Title.Content = value; }
        }

        public static StringFilterElementControl Create(FilterElementType showType, string title = "",
                                                        VoidDelegate del = null,
                                                        List<object> filterItems = null)
        {
            var control = new StringFilterElementControl { FilterTitle = title, _showType = showType };

            switch (showType)
            {
                case FilterElementType.StringList:
                    control.ContainsContainer.Visibility = Visibility.Collapsed;
                    GenerateFilterList(control, filterItems);
                    break;
                case FilterElementType.StringContains:
                    control.ListContainer.Visibility = Visibility.Collapsed;
                    break;
                case FilterElementType.StringListContains:
                    GenerateFilterList(control, filterItems);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("showType");
            }

            control.OnFilterUpdated = del;
            return control;
        }

        static void GenerateFilterList(StringFilterElementControl control, IEnumerable<object> filterItems)
        {
            if (filterItems != null)
                foreach (var item in filterItems)
                {
                    control._filterItems.Add(FilterListItem.Create(item.ToString(), control.OnCBClick));
                }

            control.FilterItemsList.ItemsSource = control._filterItems;
        }

        void OnCBClick(bool newState, string item)
        {
            if (newState)
            {
                if (!_availableItems.Contains(item))
                    _availableItems.Add(item);
            }
            else
            {
                if (_availableItems.Contains(item))
                    _availableItems.Remove(item);
            }
            if (OnFilterUpdated != null)
                OnFilterUpdated();
        }

        public void SetFilterActiveValues(FilterElementType valuesType, List<object> values)
        {
            switch (valuesType)
            {
                case FilterElementType.StringList:
                    var iList = values.Where(value => !FilterItemsList.Items.Contains(value)).ToList();
                    if(iList.Any())
                        AddFilterItems(iList);
                    foreach (ListViewItem item in FilterItemsList.Items)
                    {
                        if (values.Contains((item as FilterListItem).Title))
                            (item as FilterListItem).IsChecked = true;
                    }
                    ListCheckBox.IsChecked = true;
                    ListCheckBox_OnClick(ListCheckBox, null);
                    break;
                case FilterElementType.StringContains:
                    FilterContainsBox.Clear();
                    var sb = new StringBuilder();
                    foreach (var value in values)
                    {
                        sb.AppendLine(value.ToString());
                    }
                    FilterContainsBox.AppendText(sb.ToString());
                    ContainsCheckBox.IsChecked = true;
                    ContainsCheckBox_OnClick(ContainsCheckBox, null);
                    break;
                default:
                    throw new ArgumentOutOfRangeException("valuesType");
            }
        }

        public void AddFilterItems(List<object> filterItems)
        {
            if (_showType != FilterElementType.StringList && _showType != FilterElementType.StringListContains)
                return;
            foreach (var item in filterItems)
            {
                _filterItems.Add(FilterListItem.Create(item.ToString(), OnCBClick));
            }
        }
        
        public void SetFilterItems(List<object> filterItems)
        {
            if (_showType != FilterElementType.StringList && _showType != FilterElementType.StringListContains)
                return;
            _filterItems.Clear();
            foreach (var item in filterItems)
            {
                _filterItems.Add(FilterListItem.Create(item.ToString(), OnCBClick));
            }
        }

        public bool CheckElement(object elementToCheck)
        {
            bool contains = false;
            bool listcontains = false;
            if (_containsEnabled)
            {
                foreach (var boxString in _containBoxStrings)
                {
                    if (elementToCheck.ToString().ToLowerInvariant().Contains(boxString.ToLowerInvariant()))
                    {
                        contains = true;
                        break;
                    }
                }
            }
            if (_showType == FilterElementType.StringList || _showType == FilterElementType.StringListContains)
            {
                if (_listEnabled)
                {
                    if (_availableItems.Contains(elementToCheck))
                        listcontains = true;
                }
            }
            if ((!_containsEnabled || (_containsEnabled && contains))
                && (!_listEnabled || (_listEnabled && listcontains)))
                return true;
            return false;
        }

        private List<string> GetContainsBoxStrings()
        {
            var lcount = FilterContainsBox.LineCount;
            var lines = new List<string>();
            if (lcount < 0)
            {
                var text = FilterContainsBox.Text;
                lcount = text.Count(x => x.Equals('\n')) + 1;
                lines = text.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).ToList();
            }
            else
            {
                for (int i = 0; i < lcount; i++)
                {
                    var text = FilterContainsBox.GetLineText(i);
                    if (!string.IsNullOrWhiteSpace(text))
                        lines.Add(text);
                }
            }
            return lines;
        }

        private void FilterContainsBox_OnTextChanged(object sender, TextChangedEventArgs e)
        {
            _containBoxStrings.AddRange(GetContainsBoxStrings());
            /*for (int i = 0; i < lcount; i++)
            {
                _containBoxStrings.Add(FilterContainsBox.GetLineText(i));
            }*/
            if (OnFilterUpdated != null)
                OnFilterUpdated();
        }
        
        public void Clear()
        {
            foreach (var item in _filterItems)
            {
                item.IsChecked = false;
            }
            FilterContainsBox.Clear();
            
            ListboxCheckStateChanged(false);
            ContainsboxCheckStateChanged(false);
            ListCheckBox.IsChecked = false;
            ContainsCheckBox.IsChecked = false;
            OnFilterUpdated();
        }

        public UIElement GetElement()
        {
            return this;
        }

        public VoidDelegate OnFilterUpdated { get; set; }

        public List<object> ForRequestString
        {
            get
            {
                var toRet = new List<object>(_availableItems.Count);
                toRet.AddRange(FilterItemsList.IsEnabled
                                   ? _availableItems.Select(item => item.ToString())
                                   : new string[0]);
                if(FilterContainsBox.IsEnabled)
                    toRet.AddRange(GetContainsBoxStrings());
                return toRet;
            }
        }

        /// <summary>
        /// Элемент для списка вариантов фильтра.
        /// </summary>
        class FilterListItem : ListViewItem
        {
            private readonly StackPanel _panel;
            private readonly CheckBox _check;
            private readonly TextBlock _title;
            private readonly OnCheckBoxClickDelegate _onChangeState;

            private FilterListItem(string title, OnCheckBoxClickDelegate onClick)
            {
                _onChangeState = onClick;
                _panel = new StackPanel { Orientation = Orientation.Horizontal };
                //Orientation = Orientation.Horizontal;
                _check = new CheckBox { VerticalAlignment = VerticalAlignment.Center, IsThreeState = false };
                _check.Checked += (sender, args) =>
                    {
                        if (_onChangeState != null)
                            _onChangeState(true, _title.Text);
                    };
                _check.Unchecked += (sender, args) =>
                    {
                        if (_onChangeState != null)
                            _onChangeState(false, _title.Text);
                    };
                _title = new TextBlock { Text = title, Margin = new Thickness(5, 0, 5, 0), VerticalAlignment = VerticalAlignment.Center };
                _panel.Children.Add(_check);
                _panel.Children.Add(_title);
                Content = _panel;
                //Children.Add(_check);
                //Children.Add(_title);
            }

            public static FilterListItem Create(string title, OnCheckBoxClickDelegate onClick)
            {
                var fItem = new FilterListItem(title, onClick);
                return fItem;
            }

            public bool IsChecked
            {
                get { return _check.IsChecked == true; }
                set { _check.IsChecked = value; }
            }

            public String Title {get { return _title.Text; }}
        }


        private void ListCheckBox_OnClick(object sender, RoutedEventArgs e)
        {
            var box = (CheckBox) sender;
            ListboxCheckStateChanged(box.IsChecked == true);
            OnFilterUpdated();
        }

        void ListboxCheckStateChanged(bool active)
        {
            if (active)
            {
                FilterItemsList.IsEnabled = true;
                _listEnabled = true;
            }
            else
            {
                FilterItemsList.IsEnabled = false;
                _listEnabled = false;
            }
        }

        private void ContainsCheckBox_OnClick(object sender, RoutedEventArgs e)
        {
            var box = (CheckBox)sender;
            ContainsboxCheckStateChanged(box.IsChecked == true);
            OnFilterUpdated();
        }

        void ContainsboxCheckStateChanged(bool active)
        {
            if (active)
            {
                FilterContainsBox.IsEnabled = true;
                _containsEnabled = true;
            }
            else
            {
                FilterContainsBox.IsEnabled = false;
                _containsEnabled = false;
            }
        }
    }
}
